package org.myfram.flink.flinkonjar.common.util;

import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.introspector.Property;
import org.yaml.snakeyaml.introspector.PropertyUtils;

import java.io.InputStream;
import java.util.Map;

/**
 * @author ACC
 * @desc
 * @create 2024/07/30
 */
public class YamlUtils {

    @SuppressWarnings("unchecked")
    public static <T> T getObject(String prefix, Class<T> clazz) {
        Yaml yaml = new Yaml();
        InputStream inputStream = YamlUtils.class
                .getClassLoader()
                .getResourceAsStream("application.yml");

        Map<String, Object> data = yaml.load(inputStream);

        if (data == null) {
            return null;
        }

        String[] keys = prefix.split("\\.");
        Map<String, Object> current = data;
        for (int i = 0; i < keys.length - 1; i++) {
            current = (Map<String, Object>) current.get(keys[i]);
            if (current == null) {
                return null;
            }
        }

        Object targetConfig = current.get(keys[keys.length - 1]);

        if (targetConfig == null) {
            return null;
        }

        PropertyUtils propertyUtils = new PropertyUtils() {
            @Override
            public Property getProperty(Class<?> type, String name) {
                if (name.indexOf('-') > -1) {
                    name = toCamelCase(name);
                }
                return super.getProperty(type, name);
            }
        };

        LoaderOptions loaderOptions = new LoaderOptions();
        Constructor constructor = new Constructor(clazz, loaderOptions);
        constructor.setPropertyUtils(propertyUtils);
        Yaml yamlForParsing = new Yaml(constructor);

        return yamlForParsing.loadAs(new Yaml().dump(targetConfig), clazz);
    }

    private static String toCamelCase(String name) {
        StringBuilder sb = new StringBuilder();
        boolean upperCase = false;
        for (char c : name.toCharArray()) {
            if (c == '-') {
                upperCase = true;
            } else if (upperCase) {
                sb.append(Character.toUpperCase(c));
                upperCase = false;
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }
}